package com.atguigu.scala.ch12.sec01

/**
  * 14.1 隐式转换
  * 隐式转换函数是以 implicit 关键字声明的带有单个参数的函数。这种函数将会自动应用，将值从一种类型转换为另一种类型。
  * Scala会考虑如下的隐式转换函数:
  * 1)位于源或目标类型的伴生对象中的隐式函数。
  * 2)位于当前作用域可以以单 个标识符指代的隐式函数。
  * 隐式转换-般发生在三种情况下:
  * 1)当表达式的类型和预期类型不一致的时候。
  * 2)当对象访问一个不存在的成员时。
  * 3)当对象调用某个方法，而该方法的参数声明和传入参数不匹配时。
  * 隐式参数一般从两个地方进行查找:
  * 1)在当前作用域所有可以用单个标识符指代的满足类型要求的val和def
  * 2)该值需要声明为implicit
  */

import scala.language.implicitConversions
import scala.math._

class Fraction(n: Int, d: Int) {
  private val num: Int = if (d == 0) 1 else n * sign(d) / gcd(n, d);
  private val den: Int = if (d == 0) 0 else d * sign(d) / gcd(n, d);
  override def toString = num + "/" + den
  def sign(a: Int) = if (a > 0) 1 else if (a < 0) -1 else 0
  def gcd(a: Int, b: Int): Int = if (b == 0) abs(a) else gcd(b, a % b)

  def *(other: Fraction) = new Fraction(num * other.num, den * other.den)
}

object Fraction {
  def apply(n: Int, d: Int) = new Fraction(n, d)

}


/**
  * 这里以上就是在不修改类的情况下，给类增加新的功能
  * @param fraction
  */
class  BeautifyFraction1(fraction:Fraction){
  def beautify1 = "<<"+fraction+">>"
}

object  BeautifyFraction1{
  implicit def fraction2BeautifyFraction1(fraction: Fraction) = new BeautifyFraction1(fraction)
}

import  BeautifyFraction1._



object Main extends App {
  implicit def int2Fraction(n: Int) = Fraction(n, 1)
  val result = 3 * Fraction(4, 5) // Calls int2Fraction(3)
  println(result)
  println(Fraction(4,5)*Fraction(3,5))
  println(Fraction(4,5).beautify1)
}
